package edu.qichen.onlineBlog.user.controller;

import cn.hutool.core.util.StrUtil;

import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import edu.qichen.onlineBlog.framework.DataResult;
import edu.qichen.onlineBlog.framework.LoginAnnotation;
import edu.qichen.onlineBlog.framework.OperationAnnotation;
import edu.qichen.onlineBlog.framework.exception.BusinessException;
import edu.qichen.onlineBlog.framework.exception.ErrorCodeEnum;
import edu.qichen.onlineBlog.framework.utils.RedisUtils;
import edu.qichen.onlineBlog.framework.utils.TokenUtils;
import edu.qichen.onlineBlog.user.dto.*;
import edu.qichen.onlineBlog.user.pojo.User;
import edu.qichen.onlineBlog.user.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static edu.qichen.onlineBlog.framework.exception.ErrorCodeEnum.CURRENT_LOGIN_USER;

/**
 * 功能:用户
 * 作者:程序员欧阳子韩
 * 日期:2024/3/27 17:05
 */

@RestController
@Slf4j
@RequestMapping("/user")
@Tag(name = "用户接口")
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private RedisUtils redisUtils;

    /**
     * 根据id查找
     *
     * @param id -
     * @return -
     */
    @GetMapping("{id}")
    @Operation(summary = "根据id查找", description = "id")
    public DataResult<User> queryById(@PathVariable("id") Long id) {
        return DataResult.success(userService.getById(id));
    }

    /**
     * 查询所有用户信息
     *
     * @return -
     */
    @Operation(summary = "查询所有用户信息")
    @GetMapping("/userInfo")
    @OperationAnnotation(content = "查询所有用户信息", sysType = 0, opType = 4, action = "成功")
    public DataResult<List<User>> userInfo() {
        List<User> users = userService.queryUserInfo();

        return DataResult.success(users);
    }

    /**
     * 用户信息分页
     *
     * @param pageUserReq -
     * @return -
     */
    @Operation(summary = "用户信息分页")
    @PostMapping("/userPage")
    public DataResult<PageUserRes> userPage(@RequestBody PageUserReq pageUserReq) {
        return DataResult.success(userService.userPage(pageUserReq));
    }

    /**
     * 登录
     *
     * @param userLoginReq -
     * @return -
     */
    @Operation(summary = "登录")
    @PostMapping("/login")
    @OperationAnnotation(content = "登录博客", sysType = 0, opType = 0, action = "成功")
    @LoginAnnotation
    public DataResult<?> login(@RequestBody UserLoginReq userLoginReq, HttpServletRequest request) {
        return DataResult.success(userService.login(userLoginReq, request));
    }

    /**
     * 注册
     *
     * @param userRegisterReq -
     * @return -
     */
    @Operation(summary = "注册")
    @PostMapping("/register")
    @OperationAnnotation(content = "注册并登录博客/创建用户", sysType = 0, opType = 1, action = "成功")
    @LoginAnnotation
    public DataResult<?> register(@RequestBody UserRegisterReq userRegisterReq, HttpServletRequest request) {
        if (userService.findByEmail(userRegisterReq.getEmail())) {
            return DataResult.fail(ErrorCodeEnum.EMAIL_EXIST_ERROR);
        }
        // 获取验证码
        String code = (String) redisUtils.get(userRegisterReq.getEmail());

        if (StrUtil.isBlank(userRegisterReq.getEmail()) || StrUtil.isBlank(userRegisterReq.getCode())) {
            return DataResult.fail(ErrorCodeEnum.EMAIL_OR_CODE_ERROR);
        } else if (!userRegisterReq.getCode().equals(code)) {
            return DataResult.fail(ErrorCodeEnum.CODE_EQ_ERROR);
        }

        UserLoginRes users = userService.register(userRegisterReq, request);
        return DataResult.success(users);
    }

    /**
     * 新增用户信息
     *
     * @param userAddReq -
     * @return -
     */
    @Operation(summary = "新增用户信息")
    @PostMapping("/addUser")
    @OperationAnnotation(content = "新增用户信息", sysType = 0, opType = 1, action = "成功")
    public DataResult<User> addUser(@RequestBody UserAddReq userAddReq, HttpServletRequest request) {
        return DataResult.success(userService.addUser(userAddReq, request));
    }

    /**
     * 根据id更新用户信息
     *
     * @param userUpdateReq -
     * @return -
     */
    @Operation(summary = "根据id更新用户信息")
    @PutMapping("/updateInfo")
    @OperationAnnotation(content = "根据id更新用户信息", sysType = 0, opType = 3, action = "成功")
    public DataResult<?> updateInfo(@RequestBody UserUpdateReq userUpdateReq, HttpServletRequest request) {
        if (StrUtil.isBlank(userUpdateReq.getNickname()) || StrUtil.isBlank(userUpdateReq.getEmail())) {
            return DataResult.fail(ErrorCodeEnum.EMAIL_OR_CODE_ERROR);
        }
        User users = userService.updateUser(userUpdateReq, request);
        return DataResult.success(users);
    }

    /**
     * 修改密码
     *
     * @param updatePwdReq -
     * @return -
     */
    @Operation(summary = "修改密码")
    @PutMapping("/updatePwd")
    @OperationAnnotation(content = "修改密码", sysType = 0, opType = 3, action = "成功")
    public DataResult<Boolean> updatePwd(@RequestBody UpdatePwdReq updatePwdReq, HttpServletRequest request) {
        return DataResult.success(userService.updatePwd(updatePwdReq, request));
    }

    /**
     * 根据 id 删除用户
     *
     * @param id -
     * @return -
     */
    @Operation(summary = "根据 id 删除用户")
    @DeleteMapping("/deleteById")
    @OperationAnnotation(content = "根据 id 删除用户", sysType = 0, opType = 2, action = "成功")
    public DataResult<Boolean> deleteById(Long id, HttpServletRequest request) {
        User currentUser = TokenUtils.getCurrentUser();
        assert currentUser != null;
        if (id.equals(currentUser.getId())) {
            throw BusinessException.build(CURRENT_LOGIN_USER);
        }
        return DataResult.success(userService.deleteById(id, request));
    }

    @Operation(summary = "根据id 批量删除用户")
    @DeleteMapping("/deleteByIds")
    @OperationAnnotation(content = "根据id 批量删除用户", sysType = 0, opType = 2, action = "成功")
    @Transactional(rollbackFor = Exception.class)
    public DataResult<Void> deleteByIds(@RequestBody List<Long> ids) {
        User currentUser = TokenUtils.getCurrentUser();
        assert currentUser != null;
        if (ids.contains(currentUser.getId())) {
            throw BusinessException.build(CURRENT_LOGIN_USER);
        }
        userService.removeBatchByIds(ids);
        return DataResult.success();
    }

//    @Operation(summary = "导出用户数据")
//    @PostMapping("/export")
//    @OperationAnnotation(content = "导出用户数据", sysType = 0, opType = 6, action = "成功")
//    public void export(HttpServletResponse response, UserExportDTO user,HttpServletRequest request) {
//        List<UserExportDTO> users = userService.selectUserList(user,request);
//        ExcelUtil<UserExportDTO> util = new ExcelUtil<UserExportDTO>(UserExportDTO.class);
//        util.exportExcel(response, users, "用户数据");
//    }


    @Operation(summary = "批量导出用户数据")
    @GetMapping("/export")
    @OperationAnnotation(content = "导出用户数据", sysType = 0, opType = 6, action = "成功")
    public void exportData(@RequestParam(required = false) String username,
                           @RequestParam(required = false) String nickname,
                           @RequestParam(required = false) String ids,
                           HttpServletResponse response) {
        try {
            ExcelWriter writer = ExcelUtil.getWriter();
            List<UserExportDTO> list;
            if (StrUtil.isNotBlank(ids)) {
                List<Integer> idsList = Arrays.stream(ids.split(",")).map(Integer::valueOf).collect(Collectors.toList());
                list = userService.selectUserExportList(username, nickname, idsList);
            } else {
                // 全部导出
                list = userService.selectUserExportList(username, nickname, null); // 查询出当前需要的所有数据
            }

            writer.write(list, true);

            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
            String filename = "用户信息表_" + new Date().getTime();
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8) + ".xlsx");
            ServletOutputStream outputStream = response.getOutputStream();
            writer.flush(outputStream, true);
            writer.close();
            outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Operation(summary = "批量导入用户数据")
    @PostMapping("/import")
    @OperationAnnotation(content = "批量导入用户数据", sysType = 0, opType = 6, action = "成功")
    public DataResult importData(MultipartFile file) {
        try {
            ExcelReader reader = ExcelUtil.getReader(file.getInputStream());
            List<UserExportDTO> userExportDTOS = reader.readAll(UserExportDTO.class);
            userService.insert(userExportDTOS);
        } catch (IOException e) {
            e.printStackTrace();
            return DataResult.fail("批量导入数据错误!");
        }
        return DataResult.success();
    }
}
